/*------------------------------------------------------------------------------*\
**   Copyright 2008-2009 Jonhnny Weslley                                        **
**                                                                              **
**   Licensed under the Apache License, Version 2.0 (the "License");            **
**   you may not use this file except in compliance with the License.           **
**   You may obtain a copy of the License at                                    **
**                                                                              **
**       http://www.apache.org/licenses/LICENSE-2.0                             **
**                                                                              **
**   Unless required by applicable law or agreed to in writing, software        **
**   distributed under the License is distributed on an "AS IS" BASIS,          **
**   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   **
**   See the License for the specific language governing permissions and        **
**   limitations under the License.                                             **
\*------------------------------------------------------------------------------*/

package org.scalashell

import scala.collection.mutable.Map

object ShellSystem {

  val messages = new CompositeMessageSource

  addMessageSource("library")
  addMessageSource("org.scalashell.messages")

  System.setOut(new RenderStream(System.out))
  System.setErr(new RenderStream(System.err))

  def addMessageSource(source: String) = messages addSource source

  def apply(key: String) = System.getProperty(key)

  def apply(key: String, default: String) = System.getProperty(key, default)

  private val commandMap = Map[String, Command]()

  def addCommand(command: Command) = commandMap + ((command.name, command))

  def getCommand(commandName: String) = commandMap get commandName

  def commands = commandMap.values

  def isCommand(line: String) = commandMap.get(parseCommand(line)(0)) match {
    case Some(_) => true
    case None => false
  }

  def execute(line: String) = {
    var args = parseCommand(line)
    val commandName = args(0)
    commandMap get commandName match {
      case Some(command) => {
        args = if (args.length == 1) Nil else args.drop(1)
        command.execute(args)
      }
      case None => error("Unknow command: " + commandName)
    }
  }

  private def parseCommand(line: String) = line.trim.split(" ").toList

}

sealed class RenderStream(out: java.io.OutputStream) extends java.io.PrintStream(out, true) with terminal.Renderer {

  override def print(text: String) = {
    val toRender = if (isRenderable(text)) render(text) else text  
    super.print(toRender)
  }

}